﻿/// <reference path="_namespace.js" />
/// <reference path="../math/Vector3.js" />
/// <reference path="../math/Matrix.js" />

/*****************************************************************************
Ajax library class definition. Kevin Robinson 2008.
Class: ajax.xna.Movable
/*****************************************************************************/

ajax.lang.addNamespace("ajax.xna");
$imports("ajax.math.Matrix");
$imports("ajax.math.Vector3");

//-----------------------------------------------------------------------------
ajax.xna.Moveable = function(doc)
{    
    ajax.xna.Moveable.superConstructor.call(this, doc);
    this._initialize();
}
$extend("ajax.xna.Moveable", "ajax.components.Component");

// Statics
ajax.xna.Moveable.cast = function(obj)
{///<returns type="ajax.xna.Moveable"/>
    return obj;
}

//-----------------------------------------------------------------------------
// public properties
ajax.xna.Moveable.prototype._localMatrix            = ajax.math.Matrix.prototype;
ajax.xna.Moveable.prototype._worldMatrix            = ajax.math.Matrix.prototype;
ajax.xna.Moveable.prototype._oldLocalPositionVector = ajax.math.Vector3.prototype;
ajax.xna.Moveable.prototype._oldWorldPositionVector = ajax.math.Vector3.prototype;

//-----------------------------------------------------------------------------
// Public Accessors
ajax.xna.Moveable.prototype.getWorldMatrix = function()
{///<returns type="ajax.math.Matrix"/>
    return this._worldMatrix;
}
ajax.xna.Moveable.prototype.setWorldMatrix = function(value){ this._worldMatrix = value; }
ajax.xna.Moveable.prototype.getLocalMatrix = function()
{///<returns type="ajax.math.Matrix"/>
    return this._localMatrix;
}
ajax.xna.Moveable.prototype.setLocalMatrix = function(value) { this._localMatrix = value; }
ajax.xna.Moveable.prototype.getPositionVector = function()
{///<returns type="ajax.math.Vector3"/>
    return this._localMatrix.getPositionVector();
}
ajax.xna.Moveable.prototype.setPositionVector = function(value){ this._localMatrix.setPositionVector(value); }
ajax.xna.Moveable.prototype.getOldWorldPositionVector = function()
{///<returns type="ajax.math.Vector3"/>
    // return a COPY of the old position vector
    return ajax.math.Vector3.createFrom(this._oldWorldPositionVector);
}
ajax.xna.Moveable.prototype.setOldWorldPositionVector = function(value) { this._oldWorldPositionVector = value; }
ajax.xna.Moveable.prototype.getOldLocalPositionVector = function()
{///<returns type="ajax.math.Vector3"/>
    // Return a COPY!
    return ajax.math.Vector3.createFrom(this._oldLocalPositionVector);
}
ajax.xna.Moveable.prototype.setOldLocalPositionVector = function(value) { this._oldLocalPositionVector = value; }


//-----------------------------------------------------------------------------
// Save Methods
ajax.xna.Moveable.prototype.saveWorldPosition = function()
{///<summary>Stores the current WORLD position</summary>
    this.setOldWorldPositionVector(this._worldMatrix.getPositionVector());
}
ajax.xna.Moveable.prototype.saveLocalPosition = function()
{///<summary>Stores the current LOCAL position</summary>
    this.setOldLocalPositionVector(this._localMatrix.getPositionVector());
}

// Rotation Methods
ajax.xna.Moveable.prototype.rotateY = function(floatAngle)
{
    this._localMatrix.multiplyReversed(ajax.math.Matrix.rotateY(floatAngle));
}
ajax.xna.Moveable.prototype.rotateX = function(floatAngle)
{
    this._localMatrix.multiplyReversed(ajax.math.Matrix.rotateX(floatAngle));
}
ajax.xna.Moveable.prototype.rotateZ = function(floatAngle)
{
    this._localMatrix.multiplyReversed(ajax.math.Matrix.rotateZ(floatAngle));
}

// Move methods
ajax.xna.Moveable.prototype.move = function(floatDistance)
{///<summary>Moves this object forward in the direction it is pointing</summary>
    // When we move we always work in our local space
    // We want to move our object forwards in the direction is pointing
    var workMat     = this._localMatrix;
    var vMovement   = ajax.math.Vector3.multiplyScalar(workMat.getForwardUnitVector(), floatDistance);
    var newPos      = ajax.math.Vector3.add(workMat.getPositionVector(), vMovement);
    workMat.setPositionVector(newPos);
}

ajax.xna.Moveable.prototype.strafe = function(floatDistance)
{///<summary>Moves this object TO THE SIDE (in relation to the direction it is pointing).</summary>
    // When we move we always work in our local space
    var workMat     = this._localMatrix;
    // This is the only slightly tricky one. Cross the direction and UP to find the 
    // Vector that is perpendicular
    var cross       = ajax.math.Vector3.cross(workMat.getUpUnitVector(), workMat.getForwardUnitVector());
    cross.normalize();
    var vMovement   = ajax.math.Vector3.multiplyScalar(cross, floatDistance);
    var newPos      = ajax.math.Vector3.add(workMat.getPositionVector(), vMovement);
    workMat.setPositionVector(newPos);
}

ajax.xna.Moveable.prototype.fly = function(floatDistance)
{///<summary>Moves this object UPWARDS (in relation to the direction it is pointing).</summary>
    // When we move we always work in our local space
    var workMat     = this._localMatrix;
    var vMovement   = ajax.math.Vector3.multiplyScalar(workMat.getUpUnitVector(), floatDistance);
    var newPos      = ajax.math.Vector3.add(workMat.getPositionVector(), vMovement);
    workMat.setPositionVector(newPos);
}


//-----------------------------------------------------------------------------
// Private methods
ajax.xna.Moveable.prototype._initialize = function()
{
    this._localMatrix               = ajax.math.Matrix.identity();
    this._worldMatrix               = ajax.math.Matrix.identity();
    this._oldLocalPositionVector    = new ajax.math.Vector3();
    this._oldWorldPositionVector    = new ajax.math.Vector3();    
}